package com.sec.android.app.myfiles.module.local.recent;

import android.app.LoaderManager.LoaderCallbacks;
import android.content.Context;
import android.content.CursorLoader;
import android.content.Loader;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.SparseBooleanArray;
import android.view.KeyEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.ListView;
import android.widget.TextView;

import com.sec.android.app.myfiles.R;
import com.sec.android.app.myfiles.facade.MyFilesFacade;
import com.sec.android.app.myfiles.facade.cmd.ToSelectModeCmd;
import com.sec.android.app.myfiles.fragment.AbsMyFilesFragment;
import com.sec.android.app.myfiles.fragment.home.HomeFragment;
import com.sec.android.app.myfiles.fragment.home.HomeFragmentItem;
import com.sec.android.app.myfiles.info.AppConstants;
import com.sec.android.app.myfiles.listener.ListenerMgr;
import com.sec.android.app.myfiles.listener.RecentInsertedFromOutOfMyFiles;
import com.sec.android.app.myfiles.listener.SystemBroadcastReceiver;
import com.sec.android.app.myfiles.listener.SystemBroadcastReceiver.OnMediaScanFinish;
import com.sec.android.app.myfiles.listener.SystemBroadcastReceiver.OnMediaUnmounted;
import com.sec.android.app.myfiles.log.Log;
import com.sec.android.app.myfiles.log.SamsungAnalyticsLog;
import com.sec.android.app.myfiles.module.abstraction.FileRecord;
import com.sec.android.app.myfiles.navigation.NavigationInfo;
import com.sec.android.app.myfiles.navigation.NavigationManager;
import com.sec.android.app.myfiles.operation.FileOperationArgs;
import com.sec.android.app.myfiles.operation.FileOperator;
import com.sec.android.app.myfiles.operation.ProgressListener;
import com.sec.android.app.myfiles.provider.DbTableInfo;
import com.sec.android.app.myfiles.provider.PrivateMyFilesProvider;
import com.sec.android.app.myfiles.util.PreferenceUtils;
import com.sec.android.app.myfiles.util.UiUtils;

import java.util.ArrayList;

public class RecentHomeItem extends HomeFragmentItem implements LoaderCallbacks<Cursor>, AdapterView.OnItemClickListener, AdapterView.OnItemLongClickListener, View.OnKeyListener,
        HomeFragmentItem.SelectableItem, ProgressListener, OnMediaUnmounted, OnMediaScanFinish {
    private RecentAdapterImp mAdapterImp;
    private RecentGridView mGridView;
    private HomeFragment mHomeFragment;
    private ListenerMgr mListenerMgr;

    public RecentHomeItem(Context context, HomeFragment fragment) {
        super(context, fragment);
        mHomeFragment = fragment;
        mListenerMgr = new ListenerMgr();
        mListenerMgr.addListener(new SystemBroadcastReceiver(mContext, this,
                ListenerMgr.LifeCycle.RESUME, ListenerMgr.LifeCycle.PAUSE));
        mListenerMgr.addListener(new RecentInsertedFromOutOfMyFiles(mContext, mUpdateRunnable,
                ListenerMgr.LifeCycle.RESUME, ListenerMgr.LifeCycle.PAUSE));
    }

    @Override
    protected void setListItem() {
        mGridView = (RecentGridView) mRootView.findViewById(R.id.recent_list);

        mAdapterImp = new RecentAdapterImp(mContext, mFragment.getNavigationInfo(), R.layout.recent_grid_item, null, 0);
        mAdapterImp.updateRecentItemMaxCount(getMaxItemCount());
        mGridView.setAdapter(mAdapterImp);
        mGridView.setOnItemClickListener(this);
        mGridView.setOnItemLongClickListener(this);
        mGridView.setOnKeyListener(this);
    }

    @Override
    protected void _onResume() {
        int invalidRecentCount = 0;
        Cursor cursor = mAdapterImp.getCursor();
        if (cursor != null) {
            invalidRecentCount = removeInvalidRecent(cursor);
        }
        if (invalidRecentCount == 0) {
            // refresh list for new contents from mms, wifi.
            FileRecord record = FileRecord.createFileRecord(FileRecord.StorageType.Recent, AppConstants.StoragePath.RECENT_FILES);
            if (record != null) {
                PrivateMyFilesProvider.refreshDb(mContext, record);
                reload();
            }
        }
        mListenerMgr.notifyResume();
        TextView recentFilesHeader = (TextView) mRootView.findViewById(R.id.home_recentfiles_header);
        setContentDescription(recentFilesHeader, R.string.subtitle_recent);
    }

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle bundle) {
        DbTableInfo tableInfo = RecentDbTableInfo.getInstance();
        return new CursorLoader(mContext, Uri.parse(tableInfo.getUri()), null, mAdapterImp.getSelection(), null,
                mAdapterImp.getOrderBy());
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        View homeLayout = mRootView.findViewById(R.id.home_recent);
        if (data == null) {
            mAdapterImp.changeCursor(null);
            setViewVisibility(homeLayout, View.GONE);
        } else {
            Log.d(this, "count=" + data.getCount());
            if (removeInvalidRecent(data) > 0) {
                data.close();
                mAdapterImp.changeCursor(null);
            } else {
                if (data.getCount() == 0) {
                    setViewVisibility(homeLayout, View.GONE);
                    mHomeFragment.finishActionMode();
                } else if (!PreferenceUtils.getShowRecentFiles(mContext)) {
                    setViewVisibility(homeLayout, View.GONE);
                } else {
                    setViewVisibility(homeLayout, View.VISIBLE);
                    setViewVisibility(mGridView, View.VISIBLE);
                }
                mAdapterImp.changeCursor(data);
            }
        }
    }

    private int removeInvalidRecent(Cursor data) {
        int ret = 0;
        if (!data.isClosed() && data.moveToFirst()) {
            ArrayList<FileRecord> records = new ArrayList<>();
            FileRecord record;
            do {
                record = mAdapterImp.getFileRecord(data);
                if (record != null && !record.exists(mContext)) {
                    records.add(record);
                }
            } while (data.moveToNext());
            ret = records.size();
            Log.d(this, "remove invalid recent : " + ret);
            removeRecent(records);
        }
        if (ret != 0) {
            mHomeFragment.finishActionMode();
        }
        return ret;
    }

    private void removeRecentInStorage(final String storagePath, Cursor data) {
        if (data.moveToFirst()) {
            ArrayList<FileRecord> records = new ArrayList<>();
            FileRecord record;
            String fullPath;
            do {
                record = mAdapterImp.getFileRecord(data);
                if (record != null) {
                    fullPath = record.getFullPath();
                    if (!TextUtils.isEmpty(fullPath) && fullPath.startsWith(storagePath)) {
                        records.add(record);
                    }
                }
            } while (data.moveToNext());
            removeRecent(records);
        }
    }

    private void removeRecent(ArrayList<FileRecord> recordList) {
        if (recordList != null && !recordList.isEmpty()) {
            FileOperator operator = FileOperator.getInstance(mFragment.getProcessId(), mContext, mFragment.getFragmentManager(), null);
            FileOperationArgs args = new FileOperationArgs();
            args.mProcessId = mFragment.getProcessId();
            args.mSrcList = recordList;
            operator.setOperationArgs(FileOperator.Operation.DELETE, args);
            operator.registerProgressListener(this, null);
            operator.execute();
        }
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
    }

    @Override
    public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
        boolean showRecent = PreferenceUtils.getShowRecentFiles(mContext);
        boolean possibleActionMode = NavigationManager.isPossibleToActionMode();
        if (showRecent && possibleActionMode && !(existMore() && position == mAdapterImp.getRecentItemMaxCount() - 1)) {
            SamsungAnalyticsLog.sendLog(mFragment.getProcessId(), SamsungAnalyticsLog.Event.EXTENDS_RECENT_FILES, null);
            FileRecord record = FileRecord.createFileRecord(FileRecord.StorageType.Recent, AppConstants.StoragePath.RECENT_FILES);
            NavigationInfo info = NavigationInfo.getInstance(NavigationInfo.NavigationMode.Normal, record);
            info.setStartWithSelectMode(ToSelectModeCmd.SelectModeType.SELECT_MODE);
            info.setStartSelectionPos(position);
            info.setScreenPath(SamsungAnalyticsLog.ScreenPath.RECENT_FILES);
            NavigationManager.getInstance(mFragment.getProcessId()).enter(info);
            return true;
        }

        return false;
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        boolean showRecent = PreferenceUtils.getShowRecentFiles(mContext);
        if (showRecent && UiUtils._isValidClick(parent.getId(), 600)) {
            if (existMore() && position == mAdapterImp.getRecentItemMaxCount() - 1) {
                SamsungAnalyticsLog.sendLog(mFragment.getProcessId(), SamsungAnalyticsLog.Event.EXTENDS_RECENT_FILES, null);
                FileRecord record = FileRecord.createFileRecord(FileRecord.StorageType.Recent, AppConstants.StoragePath.RECENT_FILES);
                NavigationInfo info = NavigationInfo.getInstance(NavigationInfo.NavigationMode.Normal, record);
                info.setScreenPath(SamsungAnalyticsLog.ScreenPath.RECENT_FILES);
                NavigationManager.getInstance(mFragment.getProcessId()).enter(info);
            } else {
                AbsMyFilesFragment.ActionModeType actionModeType = mFragment.getActionModeType();
                if (actionModeType == AbsMyFilesFragment.ActionModeType.NORMAL) {
                    SamsungAnalyticsLog.sendLog(mFragment.getProcessId(), SamsungAnalyticsLog.Event.TAB_RECENT_FILE, null);
                    FileRecord record = mAdapterImp.getFileRecord(position);
                    MyFilesFacade.executeRecord(mFragment.getProcessId(), mFragment.getActivity(), record);
                } else if (actionModeType == AbsMyFilesFragment.ActionModeType.SELECT_SHARE_FILE_OPERATION
                        || actionModeType == AbsMyFilesFragment.ActionModeType.SELECT_FILE_FOLDER_OPERATION
                        || actionModeType == AbsMyFilesFragment.ActionModeType.EDIT_FILE_FOLDER_OPERATION) {
                    mHomeFragment.updateActionBarMenu();
                    if (UiUtils.isTalkBackEnabled(mContext)) {
                        mAdapterImp.changeContentDescription(view, mGridView.isItemChecked(position));
                    }
                }
            }
        }
    }

    private boolean existMore() {
        return mAdapterImp.getTotalCount() > mAdapterImp.getRecentItemMaxCount();
    }

    public int getSelectedFileCount() {
        return mGridView.getCheckedItemCount();
    }

    public int getTotalFileCount() {
        int ret;
        if (existMore()) {
            ret = mAdapterImp.getRecentItemMaxCount() - 1;
        } else {
            ret = mGridView.getCount();
        }
        return ret;
    }

    @Override
    public void setCheckMode(boolean checkMode) {
        if (mAdapterImp.getCursor() != null && !mAdapterImp.getCursor().isClosed()) {
            if (checkMode) {
                mGridView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
            } else {
                unselectAll();
                mGridView.setChoiceMode(ListView.CHOICE_MODE_NONE);
            }

            mAdapterImp.setCheckMode(checkMode, false);
            mGridView.invalidateViews();
        }
    }

    @Override
    public void selectAll() {
        int len = mGridView.getCount();
        if (existMore()) {
            len = mAdapterImp.getRecentItemMaxCount() - 1;
        }
        for (int i = 0; i < len; i++) {
            mGridView.setItemChecked(i, true);
        }
    }

    @Override
    public void unselectAll() {
        SparseBooleanArray arr = mGridView.getCheckedItemPositions();
        if (arr != null) {
            int size = arr.size();
            for (int i = 0; i < size; i++) {
                if (arr.valueAt(i)) {
                    int position = arr.keyAt(i);
                    mGridView.setItemChecked(position, false);
                }
            }
        }
    }

    @Override
    public ArrayList<FileRecord> getSelectedFile() {
        ArrayList<FileRecord> ret = new ArrayList<>();
        SparseBooleanArray arr = mGridView.getCheckedItemPositions();
        if (arr != null) {
            for (int i = 0; i < arr.size(); i++) {
                if (arr.valueAt(i)) {
                    int idx = arr.keyAt(i);
                    FileRecord record = mAdapterImp.getFileRecord(idx);
                    ret.add(record);
                }
            }
        }
        return ret;
    }

    @Override
    protected void _onPause() {
        mListenerMgr.notifyPause();
    }

    @Override
    protected void _onDestroy() {
    }

    @Override
    public void onProgressChanged(String fileName, int progress, int total) {
    }

    @Override
    public void onFinished(boolean bRet, String msg, Bundle extras) {
        reload();
    }

    public void updateRecentItemLayout() {
        mGridView.setColumnWidth(mFragment.getResources().getDimensionPixelSize(R.dimen.recent_grid_item_width));
        mGridView.setNumColumns(GridView.AUTO_FIT);
        mAdapterImp.updateRecentItemMaxCount(getMaxItemCount());
    }

    private int getMaxItemCount() {
        return UiUtils.getHomeRecentMaxItemCnt(mFragment.getActivity(), mFragment.getProcessId());
    }

    @Override
    public void onMediaUnmounted(String path) {
        if (path != null) {
            Cursor cursor = mAdapterImp.getCursor();
            if (cursor != null) {
                removeRecentInStorage(path, cursor);
            }
        }
    }


    @Override
    public void onMediaScanFinish() {
        Cursor cursor = mAdapterImp.getCursor();
        if (cursor != null) {
            if (removeInvalidRecent(cursor) > 0) {
                cursor.close();
                mAdapterImp.changeCursor(null);
            }
        }
    }

    public void reload() {
        if (mFragment.isAdded()) {
            mFragment.getLoaderManager().restartLoader(1, null, this);
        }
    }

    @Override
    public boolean onKey(View view, int keyCode, KeyEvent keyEvent) {
        if (mAdapterImp.isCheckMode() && keyCode == KeyEvent.KEYCODE_ENTER) {
            View focusedView = mGridView.getSelectedView();
            if (focusedView != null) {
                if (mGridView.indexOfChild(focusedView) == mAdapterImp.getRecentItemMaxCount() - 1) {
                    return true;
                }
            }
        }
        return false;
    }

    private Runnable mUpdateRunnable = new Runnable() {
        @Override
        public void run() {
            reload();
        }
    };

}
